package tc.alert.tckejisoc.metric;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class APIMetricRecorder {
    // 使用 ConcurrentHashMap 存储各接口的滑动窗口
    private final ConcurrentHashMap<String, TimeWindowCounter> counters = new ConcurrentHashMap<>();

    // 滑动窗口配置（单位：毫秒）
    private static final long WINDOW_SIZE = 60_000L; // 1分钟窗口
    private static final long SEGMENT_SIZE = 1_000L; // 1秒为一个时间片

    public void recordRequest(String apiName) {
        counters.compute(apiName, (k, v) -> {
            if (v == null) {
                v = new TimeWindowCounter(WINDOW_SIZE, SEGMENT_SIZE);
            }
            v.increment();
            return v;
        });
    }

    public long getRequestsInMinute(String apiName) {
        TimeWindowCounter counter = counters.get(apiName);
        return counter != null ? counter.getWindowCount() : 0L;
    }

    // 滑动窗口计数器实现
    private static class TimeWindowCounter {
        private final Segment[] segments;
        private final long windowSize;
        private final long segmentSize;
        private final Lock rotateLock = new ReentrantLock();

        TimeWindowCounter(long windowSize, long segmentSize) {
            this.windowSize = windowSize;
            this.segmentSize = segmentSize;
            int segmentCount = (int) (windowSize / segmentSize);
            this.segments = new Segment[segmentCount];
            initializeSegments();
        }

        private void initializeSegments() {
            long currentTime = System.currentTimeMillis();
            for (int i = 0; i < segments.length; i++) {
                segments[i] = new Segment(currentTime - (segments.length - i) * segmentSize);
            }
        }

        void increment() {
            rotateSegments();
            getCurrentSegment().adder.increment();
        }

        long getWindowCount() {
            rotateSegments();
            long sum = 0L;
            for (Segment segment : segments) {
                sum += segment.adder.sum();
            }
            return sum;
        }

        private void rotateSegments() {
            long currentTime = System.currentTimeMillis();
            Segment currentSegment = segments[segments.length - 1];

            if (currentTime - currentSegment.start < segmentSize) {
                return;
            }

            if (rotateLock.tryLock()) {
                try {
                    long timeDiff = currentTime - currentSegment.start;
                    int segmentsToShift = (int) (timeDiff / segmentSize);

                    if (segmentsToShift > 0) {
                        System.arraycopy(
                                segments, segmentsToShift,
                                segments, 0,
                                segments.length - segmentsToShift
                        );

                        for (int i = segments.length - segmentsToShift; i < segments.length; i++) {
                            segments[i] = new Segment(currentTime - (segments.length - i - 1) * segmentSize);
                        }
                    }
                } finally {
                    rotateLock.unlock();
                }
            }
        }

        private Segment getCurrentSegment() {
            return segments[segments.length - 1];
        }

        private static class Segment {
            final long start;
            final LongAdder adder = new LongAdder();

            Segment(long start) {
                this.start = start;
            }
        }
    }

//    // 测试用例
//    public static void main(String[] args) throws InterruptedException {
//        APIMetricRecorder recorder = new APIMetricRecorder();
//        String apiName = "/api/v1/data";
//
//        // 模拟请求
//        ExecutorService executor = Executors.newFixedThreadPool(10);
//        for (int i = 0; i < 1000; i++) {
//            executor.submit(() -> recorder.recordRequest(apiName));
//        }
//
//        // 等待所有请求完成
//        executor.shutdown();
//        executor.awaitTermination(1, TimeUnit.SECONDS);
//
//        // 获取统计结果
//        System.out.println("Requests in last minute: " + recorder.getRequestsInMinute(apiName));
//    }
}